home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / smail-3.1.28 / src / pwcache.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-11  |  8.4 KB  |  344 lines

  1. /* @(#)src/pwcache.c    1.7 7/11/92 11:49:58 */
  2.  
  3. /*
  4.  *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
  5.  *    Copyright (C) 1992  Ronald S. Karr
  6.  * 
  7.  * See the file COPYING, distributed with smail, for restriction
  8.  * and warranty information.
  9.  */
  10.  
  11. /*
  12.  * pwcache:
  13.  *    manage a passwd and group entry cache.
  14.  *
  15.  * The mailer can make a large number of acesses to the passwd and
  16.  * group files while processing a message.  To increase the efficiency
  17.  * of this, we maintain a cache of entries read from each of these
  18.  * files.
  19.  */
  20. #include <stdio.h>
  21. #include <pwd.h>
  22. #include <grp.h>
  23. #include <ctype.h>
  24. #include "defs.h"
  25. #include "smail.h"
  26. #include "hash.h"
  27. #include "alloc.h"
  28. #ifndef DEPEND
  29. # include "extern.h"
  30. #endif
  31.  
  32. /* functions imported from the C library */
  33. #ifndef ANSI_C
  34. extern struct passwd *getpwnam();
  35. extern struct passwd *getpwuid();
  36. extern struct group *getgrnam();
  37. extern struct group *getgrgid();
  38. #endif
  39.  
  40. /* functions local to this file */
  41. static void fill_pw_cache();
  42. static void fill_gr_cache();
  43.  
  44. /*
  45.  * There are separate caches for four mappings:
  46.  *
  47.  * uid->username gid->groupname username->uid groupname->gid
  48.  */
  49.  
  50. /* number of entries in each cache */
  51. #ifdef    SMALL_MEMORY
  52. # define N_CACHE    5
  53. #else
  54. # define N_CACHE    31
  55. #endif
  56.  
  57. /* buffer size to hold user and group names (with ending nul byte) */
  58. #define PW_SIZE        15
  59.  
  60. /* invalid names will begin with this char */
  61. #define BAD_NAME    ('@')
  62.  
  63. /* invalid id's are set to this unlikely id */
  64. #define BAD_ID        (-10101)
  65.  
  66. /* entries for the passwd file cache */
  67. struct    pw_cache {
  68.     char pw_name[PW_SIZE];        /* name of user */
  69.     int    pw_uid;                /* uid of user */
  70.     int    pw_gid;                /* base gid of user */
  71.     char *pw_dir;            /* home directory */
  72.     int    size_pw_dir;            /* size allocated for home directory */
  73. };
  74.  
  75. /* entries for the group file cache */
  76. struct    gr_cache {
  77.     char gr_name[PW_SIZE];        /* name of group */
  78.     int gr_gid;                /* gid of group */
  79. };
  80.  
  81. /* we rely on these being initialized to nulls */
  82. static struct hash_table *uid_cache = NULL; /* uid->username cache */
  83. static struct hash_table *gid_cache = NULL; /* gid->groupname cache */
  84. static struct hash_table *user_cache = NULL; /* username->uid cache */
  85. static struct hash_table *group_cache = NULL; /* groupname->gid cache */
  86.  
  87.  
  88. /*
  89.  * uid->username, through cache
  90.  */
  91. struct passwd *
  92. getpwbyuid(uid)
  93.     int uid;
  94. {
  95.     struct pw_cache *entp, ent;
  96.     static struct passwd ret;
  97.     static char uid_buf[50];        /* big enough to hold a number */
  98.  
  99.     if (uid_cache == NULL) {
  100.     /* XXX - hash table should be associated with a block */
  101.     uid_cache = new_hash_table(N_CACHE,
  102.                    (struct block *)NULL,
  103.                    HASH_DEFAULT);
  104.     }
  105.     (void) sprintf(uid_buf, "%d", uid);
  106.     if (lookup_in_hash(uid_buf, (char **)&entp, (int *)NULL,
  107.                uid_cache) == ALREADY_HASHED)
  108.     {
  109.     if (entp->pw_name[0] == BAD_NAME) {
  110.         return NULL;
  111.     }
  112.     ret.pw_name = entp->pw_name;
  113.     ret.pw_uid = entp->pw_uid;
  114.     ret.pw_gid = entp->pw_gid;
  115.     ret.pw_dir = entp->pw_dir;
  116.     return &ret;
  117.     } else {
  118.     register struct passwd *pw;
  119.  
  120.     setpwent();
  121.     pw = getpwuid(uid);
  122.     if (pw == NULL) {
  123.         ent.pw_uid = uid;
  124.         ent.pw_name[0] = BAD_NAME;
  125.         (void) add_to_hash(uid_buf, (char *)&ent, sizeof(ent), uid_cache);
  126.         return NULL;
  127.     }
  128.     if (user_cache == NULL) {
  129.         /* XXX - hash table should be associated with a block */
  130.         user_cache = new_hash_table(N_CACHE,
  131.                     (struct block *)NULL,
  132.                     HASH_DEFAULT);
  133.     }
  134.     fill_pw_cache(pw);
  135.     return pw;
  136.     }
  137. }
  138.  
  139. /*
  140.  * gid->groupname, through cache
  141.  */
  142. struct group *
  143. getgrbygid(gid)
  144.     int gid;
  145. {
  146.     struct gr_cache *entp, ent;
  147.     static struct group ret;
  148.     static char gid_buf[50];        /* big enough to hold a number */
  149.  
  150.     if (gid_cache == NULL) {
  151.     /* XXX - hash table should be associated with a block */
  152.     gid_cache = new_hash_table(N_CACHE,
  153.                    (struct block *)NULL,
  154.                    HASH_DEFAULT);
  155.     }
  156.     (void) sprintf(gid_buf, "%d", gid);
  157.     if (lookup_in_hash(gid_buf, (char **)&entp, (int *)NULL,
  158.                gid_cache) == ALREADY_HASHED)
  159.     {
  160.     if (entp->gr_name[0] == BAD_NAME) {
  161.         return NULL;
  162.     }
  163.     ret.gr_name = entp->gr_name;
  164.     ret.gr_gid = entp->gr_gid;
  165.     return &ret;
  166.     } else {
  167.     register struct group *gr;
  168.  
  169.     setgrent();
  170.     gr = getgrgid(gid);
  171.     if (gr == NULL) {
  172.         ent.gr_gid = gid;
  173.         ent.gr_name[0] = BAD_NAME;
  174.         (void) add_to_hash(gid_buf, (char *)&ent, sizeof(ent), gid_cache);
  175.         return NULL;
  176.     }
  177.     if (group_cache == NULL) {
  178.         /* XXX - hash table should be associated with a block */
  179.         group_cache = new_hash_table(N_CACHE,
  180.                      (struct block *)NULL,
  181.                      HASH_DEFAULT);
  182.     }
  183.     fill_gr_cache(gr);
  184.     return gr;
  185.     }
  186. }
  187.  
  188. /*
  189.  * username->uid, through cache
  190.  */
  191. struct passwd *
  192. getpwbyname(user)
  193.     char *user;
  194. {
  195.     struct pw_cache *entp, ent;
  196.     static struct passwd ret;
  197.  
  198.     if ((int)strlen(user) > PW_SIZE - 1) {
  199.     return NULL;
  200.     }
  201.     if (user_cache == NULL) {
  202.     /* XXX - hash table should be associated with a block */
  203.     user_cache = new_hash_table(N_CACHE,
  204.                     (struct block *)NULL,
  205.                     HASH_DEFAULT);
  206.     }
  207.     if (lookup_in_hash(user, (char **)&entp, (int *)NULL,
  208.                user_cache) == ALREADY_HASHED)
  209.     {
  210.     if (entp->pw_uid == BAD_ID) {
  211.         return NULL;
  212.     }
  213.     ret.pw_name = entp->pw_name;
  214.     ret.pw_uid = entp->pw_uid;
  215.     ret.pw_gid = entp->pw_gid;
  216.     ret.pw_dir = entp->pw_dir;
  217.     return &ret;
  218.     } else {
  219.     register struct passwd *pw;
  220.     register char *p;
  221.  
  222.     (void) strncpy(ent.pw_name, user, PW_SIZE - 1);
  223.     for (p = ent.pw_name; *p; p++) {
  224.         *p = lowercase(*p);
  225.     }
  226.  
  227.     setpwent();
  228.     pw = getpwnam(ent.pw_name);
  229.     if (pw == NULL) {
  230.         (void) strncpy(ent.pw_name, user, PW_SIZE - 1);
  231.         ent.pw_uid = BAD_ID;
  232.         (void) add_to_hash(user, (char *)&ent, sizeof(ent), user_cache);
  233.         return NULL;
  234.     }
  235.     if (uid_cache == NULL) {
  236.         /* XXX - hash table should be associated with a block */
  237.         uid_cache = new_hash_table(N_CACHE,
  238.                        (struct block *)NULL,
  239.                        HASH_DEFAULT);
  240.     }
  241.     fill_pw_cache(pw);
  242.     return pw;
  243.     }
  244. }
  245.  
  246. /*
  247.  * groupname->gid, through cache
  248.  */
  249. struct group *
  250. getgrbyname(group)
  251.     char *group;
  252. {
  253.     struct gr_cache *entp, ent;
  254.     static struct group ret;
  255.  
  256.     if ((int)strlen(group) > PW_SIZE - 1) {
  257.     return NULL;
  258.     }
  259.     if (group_cache == NULL) {
  260.     /* XXX - hash table should be associated with a block */
  261.     group_cache = new_hash_table(N_CACHE,
  262.                      (struct block *)NULL,
  263.                      HASH_DEFAULT);
  264.     }
  265.     if (lookup_in_hash(group, (char **)&entp, (int *)NULL,
  266.                group_cache) == ALREADY_HASHED)
  267.     {
  268.     if (entp->gr_gid == BAD_ID) {
  269.         return NULL;
  270.     }
  271.     ret.gr_gid = entp->gr_gid;
  272.     ret.gr_name = entp->gr_name;
  273.     return &ret;
  274.     } else {
  275.     register struct group *gr;
  276.     register char *p;
  277.  
  278.     (void) strncpy(ent.gr_name, group, PW_SIZE - 1);
  279.     for (p = ent.gr_name; *p; p++) {
  280.         *p = lowercase(*p);
  281.     }
  282.  
  283.     setgrent();
  284.     gr = getgrnam(ent.gr_name);
  285.     if (gr == NULL) {
  286.         (void) strncpy(ent.gr_name, group, PW_SIZE - 1);
  287.         ent.gr_gid = BAD_ID;
  288.         (void) add_to_hash(group, (char *)&ent, sizeof(ent), group_cache);
  289.         return NULL;
  290.     }
  291.     if (gid_cache == NULL) {
  292.         /* XXX - hash table should be associated with a block */
  293.         gid_cache = new_hash_table(N_CACHE,
  294.                        (struct block *)NULL,
  295.                        HASH_DEFAULT);
  296.     }
  297.     fill_gr_cache(gr);
  298.     return gr;
  299.     }
  300. }
  301.  
  302. /* fill the uid and username caches from a passwd file entry */
  303. static void
  304. fill_pw_cache(pw)
  305.     register struct passwd *pw;
  306. {
  307.     struct pw_cache ent;        /* fill this with pw info */
  308.     char uid_buf[50];            /* big enough to hold a number */
  309.     register char *p;
  310.     int size_pw_dir;
  311.  
  312.     (void) strncpy(ent.pw_name, pw->pw_name, PW_SIZE - 1);
  313.     for (p = ent.pw_name; *p; p++) {
  314.     *p = lowercase(*p);
  315.     }
  316.     ent.pw_uid = pw->pw_uid;
  317.     ent.pw_gid = pw->pw_gid;
  318.     size_pw_dir = strlen(pw->pw_dir) + 1;
  319.     ent.pw_dir = xmalloc(size_pw_dir);
  320.     (void) strcpy(ent.pw_dir, pw->pw_dir);
  321.     (void) sprintf(uid_buf, "%d", pw->pw_uid);
  322.     (void) add_to_hash(uid_buf, (char *)&ent, sizeof(ent), uid_cache);
  323.     (void) add_to_hash(ent.pw_name, (char *)&ent, sizeof(ent), user_cache);
  324. }
  325.  
  326. /* fill the gid and groupname caches from a group file entry */
  327. static void
  328. fill_gr_cache(gr)
  329.     register struct group *gr;
  330. {
  331.     struct gr_cache ent;        /* fill this with gr info */
  332.     char gid_buf[50];            /* big enough to hold a number */
  333.     register char *p;
  334.  
  335.     (void) strncpy(ent.gr_name, gr->gr_name, PW_SIZE - 1);
  336.     for (p = ent.gr_name; *p; p++) {
  337.     *p = lowercase(*p);
  338.     }
  339.     ent.gr_gid = gr->gr_gid;
  340.     (void)sprintf(gid_buf, "%d", gr->gr_gid);
  341.     (void) add_to_hash(gid_buf, (char *)&ent, sizeof(ent), gid_cache);
  342.     (void) add_to_hash(ent.gr_name, (char *)&ent, sizeof(ent), group_cache);
  343. }
  344.